home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus Special 18
/
AMIGAplus Sonderheft 18 (1999)(ICP)(DE)[!].iso
/
PD
/
Spiele
/
lazymines
/
lazymines_src
/
field.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-01-03
|
27KB
|
1,026 lines
/*
* field.c
* =======
* Implements the minefield.
*
* Copyright (C) 1994-1998 Håkan L. Younes (lorens@hem.passagen.se)
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos/dos.h>
#include <exec/memory.h>
#include <exec/types.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <intuition/imageclass.h>
#include <proto/intuition.h>
#include "localize.h"
#include "display_globals.h"
#include "layout.h"
#include "images.h"
#include "counter.h"
#include "game.h"
#include "field.h"
struct field {
struct RastPort *rp;
WORD left;
WORD top;
UBYTE rows;
UBYTE columns;
UWORD mines;
UBYTE *data;
UWORD *zeros;
UWORD swept;
};
#define MINE 0x09
#define LOCKED 0x10
#define WARNED 0x20
#define SWEPT 0x40
#define PATH 0x80
#define FIELD(f, r, c) ((f)->data[(r) * (f)->columns + (c)])
#define SET_FIELD(f, r, c, v) (FIELD ((f), (r), (c)) = (v))
#define CELL_VAL(f, r, c) (FIELD ((f), (r), (c)) & 0x0F)
#define IS_ZERO(f, r, c) (CELL_VAL ((f), (r), (c)) == 0)
#define IS_MINE(f, r, c) (CELL_VAL ((f), (r), (c)) == MINE)
#define IS_LOCKED(f, r, c) (FIELD ((f), (r), (c)) & LOCKED)
#define IS_WARNED(f, r, c) (FIELD ((f), (r), (c)) & WARNED)
#define IS_SWEPT(f, r, c) (FIELD ((f), (r), (c)) & SWEPT)
#define IS_PATH(f, r, c) (FIELD ((f), (r), (c)) & PATH)
#define IS_SWEEPABLE(f, r, c) (!(FIELD ((f), (r), (c)) & (LOCKED | SWEPT)))
#define LOCK_CELL(f, r, c) (FIELD ((f), (r), (c)) |= LOCKED)
#define WARN_CELL(f, r, c) (FIELD ((f), (r), (c)) |= WARNED)
#define UNLOCK_CELL(f, r, c) (FIELD ((f), (r), (c)) &= ~(LOCKED | WARNED))
#define SWEEP_CELL(f, r, c) (FIELD ((f), (r), (c)) |= SWEPT)
#define PATH_CELL(f, r, c) (FIELD ((f), (r), (c)) |= PATH)
#define POSINFIELD(f, r, c) ((c) + (r) * (f)->columns)
#define POS2ROW(f, p) ((p) / (f)->columns)
#define POS2COL(f, p) ((p) % (f)->columns)
#define FIELDWIDTH(f) ((f)->columns * cell_w + 2 * LINEWIDTH)
#define FIELDHEIGHT(f) ((f)->rows * cell_h + 2 * LINEHEIGHT)
#define RAISEDBOX 0
#define RECESSEDBOX 1
#define THINBOX 2
static void
draw_box(
struct RastPort *rp,
WORD left,
WORD top,
UWORD width,
UWORD height,
UBYTE type)
{
if (type == THINBOX)
{
SetAPen (rp, gui_pens[SHADOWPEN]);
Move (rp, left, top);
Draw (rp, left + width - 1, top);
Draw (rp, left + width - 1, top + height - 1);
Draw (rp, left, top + height - 1);
Draw (rp, left, top);
SetAPen (rp, gui_pens[BACKGROUNDPEN]);
Move (rp, left + 1, top + 1);
Draw (rp, left + 1, top + height - 2);
Move (rp, left + width - 2, top + 1);
Draw (rp, left + width - 2, top + height - 2);
}
else
{
SetAPen(rp, gui_pens[((type == RAISEDBOX) ? SHINEPEN : SHADOWPEN)]);
Move (rp, left + width - 2, top);
Draw (rp, left, top);
Draw (rp, left, top + height - 1);
Move (rp, left + 1, top + height - 2);
Draw (rp, left + 1, top + 1);
SetAPen(rp, gui_pens[((type == RAISEDBOX) ? SHADOWPEN: SHINEPEN)]);
Move (rp, left + 1, top + height - 1);
Draw (rp, left + width - 1, top + height - 1);
Draw (rp, left + width - 1, top);
Move (rp, left + width - 2, top + 1);
Draw (rp, left + width - 2, top + height - 2);
}
}
static void
draw_cell (
struct RastPort *rp,
WORD left,
WORD top,
UBYTE value)
{
draw_box (rp, left, top, cell_w, cell_h,
((value & SWEPT) ? THINBOX : RAISEDBOX));
SetAPen (rp, gui_pens[BACKGROUNDPEN]);
RectFill (rp, left + LINEWIDTH, top + LINEHEIGHT,
left + cell_w - LINEWIDTH - 1, top + cell_h - LINEHEIGHT - 1);
if (value & SWEPT)
{
value &= 0x0F;
if (value == MINE)
DrawImageState (rp, mine_image, left, top, IDS_NORMAL, NULL);
else
{
if (value > 0)
{
char ch = value + '0';
SetAPen (rp, (game_pens[value - 1] != -1 && display_colors) ?
game_pens[value - 1] : gui_pens[TEXTPEN]);
Move (rp, left + (cell_w - rp->TxWidth) / 2,
top + (cell_h - rp->TxHeight) / 2 + rp->TxBaseline);
Text (rp, &ch, 1);
}
}
}
else if (value & LOCKED)
{
if (value & WARNED)
{
SetAPen (rp, gui_pens[TEXTPEN]);
Move (rp, left + (cell_w - rp->TxWidth) / 2,
top + (cell_h - rp->TxHeight) / 2 + rp->TxBaseline);
Text (rp, "?", 1);
}
else
DrawImageState (rp, flag_image, left, top, IDS_NORMAL, NULL);
}
}
static UBYTE
count_neighbors (
field_ptr field,
WORD row,
WORD col,
UBYTE filter)
{
register WORD r, c;
register UBYTE count = 0;
for (r = row - 1; r <= row + 1; ++r)
{
for (c = col - 1; c <= col + 1; ++c)
{
if (field_inside (field, r, c) && !(r == row && c == col) &&
(FIELD (field, r, c) & filter) == filter)
{
++count;
}
}
}
return count;
}
static void
avoid_trivial (
field_ptr field)
{
register WORD r, c, rr, cc;
UBYTE row0, col0;
UWORD pos, next;
BOOL trivial = FALSE;
if (CELL_VAL (field, 0, 0) == 0)
{
SWEEP_CELL (field, 0, 0);
pos = next = 0;
field->zeros[next++] = POSINFIELD (field, 0, 0);
while (pos < next && !trivial)
{
row0 = POS2ROW (field, field->zeros[pos]);
col0 = POS2COL (field, field->zeros[pos]);
for (r = row0 - 1; r <= row0 + 1; ++r)
{
for (c = col0 - 1; c <= col0 + 1; ++c)
{
if (field_inside (field, r, c) &&
!IS_SWEPT (field, r, c))
{
SWEEP_CELL (field, r, c);
if (r == field->rows - 1 && c == field->columns - 1)
trivial = TRUE;
if (IS_ZERO (field, r, c))
field->zeros[next++] = POSINFIELD (field, r, c);
}
}
}
++pos;
}
for (r = 0; r < field->rows; ++r)
for (c = 0; c < field->columns; ++c)
if (IS_SWEPT (field, r, c))
FIELD (field, r, c) &= ~SWEPT;
}
if (trivial)
{
row0 = col0 = r = 0;
if (!IS_PATH (field, 0, 1))
r |= 1;
if (!IS_PATH (field, 1, 0))
r |= 2;
if (!IS_PATH (field, 1, 1))
r |= 4;
if (r == 0)
{
if ((int)(2 * drand48 ()) == 0)
r |= 1;
else
r |= 2;
}
while (row0 == 0 && col0 == 0)
{
rr = 3 * drand48 ();
if (r & (1 << rr))
{
row0 = (rr == 0) ? 0 : 1;
col0 = (rr == 1) ? 0 : 1;
}
}
for (r = 0; r < field->rows && trivial; ++r)
{
for (c = 0; c < field->columns && trivial; ++c)
{
if (IS_MINE (field, r, c))
{
trivial = FALSE;
SET_FIELD (field, r, c, 0);
for (rr = r - 1; rr <= r + 1; ++rr)
{
for (cc = c - 1; cc <= c + 1; ++cc)
{
if (field_inside (field, rr, cc) &&
!IS_MINE (field, rr, cc))
{
SET_FIELD (field, rr, cc,
count_neighbors (field, rr, cc, MINE));
}
}
}
}
}
}
SET_FIELD (field, row0, col0, MINE);
for (rr = row0 - 1; rr <= row0 + 1; ++rr)
{
for (cc = col0 - 1; cc <= col0 + 1; ++cc)
{
if (field_inside (field, rr, cc) && !IS_MINE (field, rr, cc))
{
SET_FIELD (field, rr, cc,
count_neighbors (field, rr, cc, MINE));
}
}
}
}
}
static BOOL
generate_path (
field_ptr field)
{
register WORD r, c;
UBYTE row, col;
UWORD path_count, next_pos, possible_pos[8];
UBYTE count, try_count = 0;
BOOL done, failure = TRUE;
char msg[81];
ULONG char_count;
struct TextExtent te;
SetAPen (field->rp, gui_pens[BACKGROUNDPEN]);
RectFill (field->rp, field->left + LINEWIDTH, field->top + LINEHEIGHT,
field->left + FIELDWIDTH (field) - LINEWIDTH - 1,
field->top + FIELDHEIGHT (field) - LINEHEIGHT - 1);
sprintf (msg, localized_string (MSG_GENERATE_PATH), try_count + 1);
char_count = TextFit (field->rp, msg, strlen (msg), &te, NULL, 1,
FIELDWIDTH (field) - 2 * LINEWIDTH,
FIELDHEIGHT (field) - 2 * LINEHEIGHT);
SetAPen (field->rp, gui_pens[TEXTPEN]);
while (failure)
{
Move (field->rp,
field->left + (FIELDWIDTH (field) - te.te_Width) / 2,
field->top + field->rp->TxBaseline +
(FIELDHEIGHT (field) - te.te_Height) / 2);
Text (field->rp, msg, char_count);
done = FALSE;
row = col = 0;
path_count = 1;
PATH_CELL (field, row, col);
while (!done)
{
count = 0;
for (r = row - 1; r <= row + 1; ++r)
{
for (c = col - 1; c <= col + 1; ++c)
{
if (field_inside (field, r, c) && !IS_PATH (field, r, c) &&
!(col == 0 && r < row) && !(row == 0 && c < col) &&
!(col == field->columns - 1 && r < row) &&
!(row == field->rows - 1 && c < col))
{
possible_pos[count++] = POSINFIELD (field, r, c);
}
}
}
if (count > 0)
{
next_pos = possible_pos[(int)(count * drand48 ())];
row = POS2ROW (field, next_pos);
col = POS2COL (field, next_pos);
PATH_CELL (field, row, col);
++path_count;
}
if (count == 0 ||
(row == field->rows - 1 && col == field->columns - 1))
done = TRUE;
}
if (count == 0 ||
field->rows * field->columns - path_count < field->mines)
{
++try_count;
sprintf (msg, localized_string (MSG_GENERATE_PATH), try_count + 1);
if (current_level == OPTIONAL_LEVEL && try_count == 100)
return FALSE;
memset (field->data, 0,
field->rows * field->columns * sizeof (*field->data));
}
else
failure = FALSE;
}
return TRUE;
}
static void
generate_opening (
field_ptr field)
{
register UBYTE row, col, row0, col0;
register WORD r, c;
UBYTE best_row = 0, best_col = 0;
UWORD best_count = 0xFFFF, sweep_count, wanted_count;
UWORD pos, next;
wanted_count = field->rows * field->columns * (auto_opening / 100.0);
if (wanted_count == 0)
wanted_count = 1;
for (row = 0; row < field->rows; ++row)
{
for (col = 0; col < field->columns; ++col)
{
if (!(IS_MINE (field, row, col) || IS_PATH (field, row, col)))
{
sweep_count = 1;
if (CELL_VAL (field, row, col) == 0)
{
PATH_CELL (field, row, col);
pos = next = 0;
field->zeros[next++] = POSINFIELD (field, row, col);
while (pos < next)
{
row0 = POS2ROW (field, field->zeros[pos]);
col0 = POS2COL (field, field->zeros[pos]);
for (r = row0 - 1; r <= row0 + 1; ++r)
{
for (c = col0 - 1; c <= col0 + 1; ++c)
{
if (field_inside (field, r, c) &&
!IS_PATH (field, r, c))
{
PATH_CELL (field, r, c);
++sweep_count;
if (IS_ZERO (field, r, c))
field->zeros[next++] = POSINFIELD (field, r, c);
}
}
}
++pos;
}
for (r = 0; r < field->rows; ++r)
for (c = 0; c < field->columns; ++c)
if (IS_PATH (field, r, c) && !IS_ZERO (field, r, c))
FIELD (field, r, c) &= ~PATH;
}
if (abs (sweep_count - wanted_count) <
abs (best_count - wanted_count) &&
sweep_count < field->rows * field->columns - field->mines)
{
best_count = sweep_count;
best_row = row;
best_col = col;
}
}
}
}
reveal_this (field, best_row, best_col);
counter_update (time_counter, best_count / 4);
time_on = TRUE;
timer_start (timer_obj, 0L, 1000000L);
}
static void
mutate_neighbors (
field_ptr field,
WORD row,
WORD col,
UBYTE filter,
UBYTE mask)
{
register WORD r, c;
for (r = row - 1; r <= row + 1; ++r)
{
for (c = col - 1; c <= col + 1; ++c)
{
if (field_inside (field, r, c) && (r != row || r != col) &&
FIELD (field, r, c) & filter)
{
FIELD (field, r, c) &= ~mask;
}
}
}
}
static void
sweep_zero (
field_ptr field,
UBYTE row,
UBYTE col)
{
register WORD r, c;
UWORD pos = 0, next = 0;
field->zeros[next++] = POSINFIELD (field, row, col);
while (pos < next)
{
row = POS2ROW (field, field->zeros[pos]);
col = POS2COL (field, field->zeros[pos]);
for (r = row - 1; r <= row + 1; ++r)
{
for (c = col - 1; c <= col + 1; ++c)
{
if (field_inside (field, r, c) && IS_SWEEPABLE (field, r, c))
{
SWEEP_CELL (field, r, c);
++field->swept;
draw_cell (field->rp, field->left + LINEWIDTH + c * cell_w,
field->top + LINEHEIGHT + r * cell_h,
FIELD (field, r, c));
if (IS_ZERO (field, r, c))
field->zeros[next++] = POSINFIELD (field, r, c);
}
}
}
++pos;
}
}
static BOOL
reveal_around (
field_ptr field,
UBYTE row,
UBYTE col)
{
register WORD r, c;
BOOL success = TRUE;
for (r = row - 1; r <= row + 1 && success; ++r)
for (c = col - 1; c <= col + 1 && success; ++c)
if (field_inside (field, r, c) && (r != row || c != col))
success = reveal_this (field, r, c);
return success;
}
field_ptr
field_init (
struct RastPort *rp,
WORD left,
WORD top,
UBYTE rows,
UBYTE columns,
UWORD mines)
{
field_ptr field;
if (field = AllocVec (sizeof (*field), MEMF_PUBLIC))
{
field->rp = rp;
field->left = left;
field->top = top;
field->rows = rows;
field->columns = columns;
field->mines = mines;
if ((field->data = AllocVec (rows * columns *
sizeof (*field->data), MEMF_PUBLIC)) &&
(field->zeros = AllocVec (rows * columns *
sizeof (*field->zeros), MEMF_PUBLIC)))
{
return field;
}
}
field_free (field);
return NULL;
}
void
field_free (
field_ptr field)
{
if (field != NULL)
{
if (field->data != NULL)
FreeVec (field->data);
if (field->zeros != NULL)
FreeVec (field->zeros);
FreeVec (field);
}
}
WORD
field_left (
field_ptr field)
{
return field->left;
}
WORD
field_top (
field_ptr field)
{
return field->top;
}
BOOL
field_size (
field_ptr field,
UBYTE rows,
UBYTE columns,
UWORD mines)
{
field->mines = mines;
if (rows != field->rows || columns != field->columns)
{
FreeVec (field->data);
FreeVec (field->zeros);
if ((field->data = AllocVec (rows * columns *
sizeof (*field->data), MEMF_PUBLIC)) &&
(field->zeros = AllocVec (rows * columns *
sizeof (*field->zeros), MEMF_PUBLIC)))
{
field->rows = rows;
field->columns = columns;
return TRUE;
}
return FALSE;
}
return TRUE;
}
BOOL
field_inside (
field_ptr field,
WORD row,
WORD column)
{
return (BOOL)(row >= 0 && row < field->rows &&
column >= 0 && column < field->columns);
}
BOOL
field_reset (
field_ptr field)
{
STRPTR msg;
ULONG char_count;
struct TextExtent te;
UWORD n = field->mines;
register UBYTE r, c;
draw_box (field->rp, field_left (field), field_top (field),
FIELDWIDTH (field), FIELDHEIGHT (field), RECESSEDBOX);
field->swept = 0;
memset (field->data, 0,
field->rows * field->columns * sizeof (*field->data));
if (chosen_task == SWEEP_PATH && !generate_path (field))
return FALSE;
SetAPen (field->rp, gui_pens[BACKGROUNDPEN]);
RectFill (field->rp, field->left + LINEWIDTH, field->top + LINEHEIGHT,
field->left + FIELDWIDTH (field) - LINEWIDTH - 1,
field->top + FIELDHEIGHT (field) - LINEHEIGHT - 1);
msg = localized_string (MSG_INITIALIZE_FIELD);
char_count = TextFit (field->rp, msg, strlen (msg), &te, NULL, 1,
FIELDWIDTH (field) - 2 * LINEWIDTH,
FIELDHEIGHT (field) - 2 * LINEHEIGHT);
SetAPen (field->rp, gui_pens[TEXTPEN]);
Move (field->rp,
field->left + (FIELDWIDTH (field) - te.te_Width) / 2,
field->top + field->rp->TxBaseline +
(FIELDHEIGHT (field) - te.te_Height) / 2);
Text (field->rp, msg, char_count);
while (n > 0)
{
r = drand48 () * field->rows;
c = drand48 () * field->columns;
if (!(IS_MINE (field, r, c) ||
(IS_PATH (field, r, c) && chosen_task == SWEEP_PATH)))
{
SET_FIELD (field, r, c, MINE);
--n;
}
}
for (r = 0; r < field->rows; ++r)
for (c = 0; c < field->columns; ++c)
if (!IS_MINE (field, r, c))
SET_FIELD (field, r, c, count_neighbors (field, r, c, MINE));
SetAPen (field->rp, gui_pens[BACKGROUNDPEN]);
RectFill (field->rp, field->left + LINEWIDTH, field->top + LINEHEIGHT,
field->left + LINEWIDTH + cell_w - 1,
field->top + LINEHEIGHT + cell_h - 1);
draw_box (field->rp, field->left + LINEWIDTH, field->top + LINEHEIGHT,
cell_w, cell_h, RAISEDBOX);
for (r = 0; r < field->rows; ++r)
{
for (c = 0; c < field->columns; ++c)
{
if (r || c)
{
ClipBlit (field->rp,
field->left + LINEWIDTH, field->top + LINEHEIGHT,
field->rp, field->left + LINEWIDTH + c * cell_w,
field->top + LINEHEIGHT + r * cell_h,
cell_w, cell_h, 0xC0);
}
}
}
if (auto_opening > 0 && chosen_task == SWEEP_ALL)
generate_opening (field);
else if (chosen_task == SWEEP_PATH)
{
avoid_trivial (field);
chosen_task = SWEEP_ALL;
reveal_this (field, 0, 0);
chosen_task = SWEEP_PATH;
time_on = TRUE;
timer_start (timer_obj, 0L, 1000000L);
}
return TRUE;
}
void
field_draw (
field_ptr field)
{
register UBYTE r, c;
draw_box (field->rp, field_left (field), field_top (field),
FIELDWIDTH (field), FIELDHEIGHT (field), RECESSEDBOX);
for (r = 0; r < field->rows; ++r)
{
for (c = 0; c < field->columns; ++c)
{
draw_cell (field->rp, field->left + LINEWIDTH + c * cell_w,
field->top + LINEHEIGHT + r * cell_h,
FIELD (field, r, c));
}
}
}
void
field_delete (
field_ptr field)
{
SetAPen (field->rp, gui_pens[BACKGROUNDPEN]);
RectFill (field->rp, field->left, field->top,
field->left + FIELDWIDTH (field) - 1,
field->top + FIELDHEIGHT (field) - 1);
}
BOOL
reveal_this (
field_ptr field,
UBYTE row,
UBYTE col)
{
if (IS_SWEEPABLE (field, row, col) &&
(chosen_task == SWEEP_ALL || count_neighbors (field, row, col, SWEPT)))
{
SWEEP_CELL (field, row, col);
draw_cell (field->rp, field->left + LINEWIDTH + col * cell_w,
field->top + LINEHEIGHT + row * cell_h,
FIELD (field, row, col));
if (IS_MINE (field, row, col))
return FALSE;
++field->swept;
if (CELL_VAL (field, row, col) == 0)
sweep_zero (field, row, col);
}
return TRUE;
}
BOOL
sweep_this (
field_ptr field,
UBYTE row,
UBYTE col)
{
register WORD r, c;
register UBYTE lock_count = 0;
register UBYTE warn_count = 0;
register UBYTE free_count = 0;
register BOOL success = TRUE;
if (IS_SWEPT (field, row, col))
{
for (r = row - 1; r <= row + 1; ++r)
{
for (c = col - 1; c <= col + 1; ++c)
{
if (field_inside (field, r, c))
{
if (IS_WARNED (field, r, c))
++warn_count;
else if (IS_LOCKED (field, r, c))
++lock_count;
else if (!IS_SWEPT (field, r, c))
++free_count;
}
}
}
if (lock_count >= CELL_VAL (field, row, col))
{
if (warn_count)
mutate_neighbors (field, row, col, WARNED, WARNED | LOCKED);
success = reveal_around (field, row, col);
}
else if (free_count + warn_count + lock_count ==
CELL_VAL (field, row, col))
{
if (warn_count)
mutate_neighbors (field, row, col, WARNED, WARNED | LOCKED);
for (r = row - 1; r <= row + 1; ++r)
{
for (c = col - 1; c <= col + 1; ++c)
{
if (field_inside (field, r, c) && IS_SWEEPABLE (field, r, c))
{
toggle_lock (field, r, c);
}
}
}
}
}
release_around (field, row, col);
return success;
}
void
toggle_lock (
field_ptr field,
UBYTE row,
UBYTE col)
{
if (!IS_SWEPT (field, row, col))
{
if (IS_LOCKED (field, row, col))
{
if (IS_WARNED (field, row, col))
UNLOCK_CELL (field, row, col);
else
{
if (place_warnings)
WARN_CELL (field, row, col);
else
UNLOCK_CELL (field, row, col);
counter_update (flag_counter, counter_value (flag_counter) + 1);
}
draw_cell (field->rp, field->left + LINEWIDTH + col * cell_w,
field->top + LINEHEIGHT + row * cell_h,
FIELD (field, row, col));
}
else if (counter_value (flag_counter) > 0)
{
LOCK_CELL (field, row, col);
draw_cell (field->rp, field->left + LINEWIDTH + col * cell_w,
field->top + LINEHEIGHT + row * cell_h,
FIELD (field, row, col));
counter_update (flag_counter, counter_value (flag_counter) - 1);
}
}
}
void
press_this (
field_ptr field,
UBYTE row,
UBYTE col)
{
if (IS_SWEEPABLE (field, row, col) &&
(chosen_task == SWEEP_ALL || count_neighbors (field, row, col, SWEPT)))
{
draw_box (field->rp, field->left + LINEWIDTH + col * cell_w,
field->top + LINEHEIGHT + row * cell_h,
cell_w, cell_h, THINBOX);
}
}
void
press_around (
field_ptr field,
UBYTE row,
UBYTE col)
{
register WORD r, c;
if (IS_SWEPT (field, row, col))
for (r = row - 1; r <= row + 1; ++r)
for (c = col - 1; c <= col + 1; ++c)
if (field_inside (field, r, c) && (r != row || c != col))
press_this (field, r, c);
}
void
release_this (
field_ptr field,
UBYTE row,
UBYTE col)
{
if (IS_SWEEPABLE (field, row, col))
{
draw_box (field->rp, field->left + LINEWIDTH + col * cell_w,
field->top + LINEHEIGHT + row * cell_h,
cell_w, cell_h, RAISEDBOX);
}
}
void
release_around (
field_ptr field,
UBYTE row,
UBYTE col)
{
register WORD r, c;
if (IS_SWEPT (field, row, col))
for (r = row - 1; r <= row + 1; ++r)
for (c = col - 1; c <= col + 1; ++c)
if (field_inside (field, r, c) && (r != row || c != col))
release_this (field, r, c);
}
BOOL
field_swept (
field_ptr field)
{
return (BOOL)((chosen_task == SWEEP_ALL &&
field->rows * field->columns - field->mines ==
field->swept) ||
(chosen_task == SWEEP_PATH &&
IS_SWEPT (field, field->rows - 1, field->columns - 1)));
}
void
field_win (
field_ptr field)
{
register UBYTE r, c;
for (r = 0; r < field->rows; ++r)
{
for (c = 0; c < field->columns; ++c)
{
if (IS_MINE (field, r, c) &&
(IS_SWEEPABLE (field, r, c) || IS_WARNED (field, r, c)))
{
LOCK_CELL (field, r, c);
draw_cell (field->rp, field->left + LINEWIDTH + c * cell_w,
field->top + LINEHEIGHT + r * cell_h,
FIELD (field, r, c));
}
}
}
counter_update (flag_counter, 0);
}
void
field_lose (
field_ptr field)
{
register UBYTE r, c;
for (r = 0; r < field->rows; ++r)
{
for (c = 0; c < field->columns; ++c)
{
if (IS_MINE (field, r, c) && !IS_SWEPT (field, r, c))
{
SWEEP_CELL (field, r, c);
draw_cell (field->rp, field->left + LINEWIDTH + c * cell_w,
field->top + LINEHEIGHT + r * cell_h,
FIELD (field, r, c));
}
}
}
}